package com.fastloan.jn.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 时间工具类
 *
 * @author liduo
 */
public class DateTimeUtil {
    /**
     * 标准日期时间格式(yyyy-MM-dd HH:mm:ss)
     */
    public static final String NORM_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    /**
     * 去分割日期时间格式(yyyyMMddHHmmss)
     */
    public static final String DIGIT_DATETIME_PATTERN = "yyyyMMddHHmmss";
    /**
     * 标准日期格式(yyyy-MM-dd)
     */
    public static final String NORM_DATE_PATTERN = "yyyy-MM-dd";
    /**
     * 去分割日期格式(yyyyMMdd)
     */
    public static final String DIGIT_DATE_PATTERN = "yyyyMMdd";

    public static final String HH_MM_DATE_PATTERN = "HH:mm";

    /**
     * LocalDate 标准日期时间格式(yyyy-MM-dd HH:mm:ss)
     */
    public static final DateTimeFormatter NORM_DATETIME_PATTERN_L = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * 日期时间格式化器 ,格式 [yyyy-MM-dd HH:mm:ss]
     */
    private static ThreadLocal<SimpleDateFormat> normDatetimePatternFormat = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected synchronized SimpleDateFormat initialValue() {
            return new SimpleDateFormat(NORM_DATETIME_PATTERN);
        }
    };
    /**
     * 日期时间格式化器 ,格式 [yyyyMMddHHmmss]
     */
    private static ThreadLocal<SimpleDateFormat> digitDatetimePatternFormat = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected synchronized SimpleDateFormat initialValue() {
            return new SimpleDateFormat(DIGIT_DATETIME_PATTERN);
        }
    };
    /**
     * 日期格式化器, 格式[yyyy-MM-dd]
     */
    private static ThreadLocal<SimpleDateFormat> normDatePatternFormat = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected synchronized SimpleDateFormat initialValue() {
            return new SimpleDateFormat(NORM_DATE_PATTERN);
        }
    };
    /**
     * 日期格式化器, 格式[yyyyMMdd]
     */
    private static ThreadLocal<SimpleDateFormat> digitDatePatternFormat = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected synchronized SimpleDateFormat initialValue() {
            return new SimpleDateFormat(DIGIT_DATE_PATTERN);
        }
    };
    /**
     * 日期格式化器, 格式[HH:mm]
     */
    private static ThreadLocal<SimpleDateFormat> hhMMDatePatternFormat = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected synchronized SimpleDateFormat initialValue() {
            return new SimpleDateFormat(HH_MM_DATE_PATTERN);
        }
    };

    /**
     * 获取当前日期或时间
     *
     * @param format 日期格式,使用已有格式
     * @return 格式化后的日期字符串
     */
    public static String getNow(String format) {
        if (format.equals(NORM_DATETIME_PATTERN)) {
            return normDatetimePatternFormat.get().format(new Date());
        } else if (format.equals(DIGIT_DATETIME_PATTERN)) {
            return digitDatetimePatternFormat.get().format(new Date());
        } else if (format.equals(NORM_DATE_PATTERN)) {
            return normDatePatternFormat.get().format(new Date());
        } else if (format.equals(DIGIT_DATE_PATTERN)) {
            return digitDatePatternFormat.get().format(new Date());
        } else {
            return null;
        }
    }

    /**
     * 根据特定格式格式化日期
     *
     * @param date   日期对象
     * @param format 日期格式,使用已有格式
     * @return 格式化后的日期字符串
     */
    public static String format(Date date, String format) {
        // 如果默认date为
        if (date == null) {
            return null;
        }
        if (format.equals(NORM_DATETIME_PATTERN)) {
            return normDatetimePatternFormat.get().format(date);
        } else if (format.equals(DIGIT_DATETIME_PATTERN)) {
            return digitDatetimePatternFormat.get().format(date);
        } else if (format.equals(NORM_DATE_PATTERN)) {
            return normDatePatternFormat.get().format(date);
        } else if (format.equals(DIGIT_DATE_PATTERN)) {
            return digitDatePatternFormat.get().format(date);
        } else if(format.equals(HH_MM_DATE_PATTERN)){
            return hhMMDatePatternFormat.get().format(date);
        }else {
            return null;
        }
    }

    /**
     * 把字符串解析转化成一个日期
     * <p>
     * 注意传送的日期字符串要和日期格式对应例如：<br>
     * format("20141212",DateTimeUtil.DIGIT_DATE_PATTERN)
     *
     * @param strDate 日期字符串
     * @param format  日期格式
     * @return 返回日期Date对象
     * @throws ParseException 日期字符串和格式不对应，解析异常
     */
    public static Date format(String strDate, String format)
            throws ParseException {
        if (null == strDate || "".equals(strDate)) {
            return null;
        }
        if (format.equals(NORM_DATETIME_PATTERN)) {
            return normDatetimePatternFormat.get().parse(strDate);
        } else if (format.equals(DIGIT_DATETIME_PATTERN)) {
            return digitDatetimePatternFormat.get().parse(strDate);
        } else if (format.equals(NORM_DATE_PATTERN)) {
            return normDatePatternFormat.get().parse(strDate);
        } else if (format.equals(DIGIT_DATE_PATTERN)) {
            return digitDatePatternFormat.get().parse(strDate);
        } else {
            return null;
        }
    }

    /**
     * 将String型格式化,比如想要将2011-11-11格式化成2011年11月11日,就StringPattern("2011-11-11","yyyy-MM-dd","yyyy年MM月dd日").
     *
     * @param date       String 想要格式化的日期
     * @param oldPattern String 想要格式化的日期的现有格式
     * @param newPattern String 想要格式化成什么格式
     * @return String
     */
    public final static String stringPattern(String date, String oldPattern, String newPattern) {
        if (date == null || oldPattern == null || newPattern == null) {
            return "";
        }
        SimpleDateFormat sdf1 = new SimpleDateFormat(oldPattern);        // 实例化模板对象
        SimpleDateFormat sdf2 = new SimpleDateFormat(newPattern);        // 实例化模板对象
        Date d = null;
        try {
            d = sdf1.parse(date);   // 将给定的字符串中的日期提取出来
        } catch (Exception e) {            // 如果提供的字符串格式有错误，则进行异常处理
            e.printStackTrace();       // 打印异常信息
        }
        return sdf2.format(d);
    }

    /**
     * 计算两个日期间隔时间
     *
     * @param beginTime 开始时间
     * @param nowTime   现在时间
     * @return 间隔时间
     */
    public static Map<String, Object> dateSubtraction(Date beginTime, Date nowTime) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(beginTime);
        int beginDay = calendar.get(Calendar.DAY_OF_MONTH);
        int beginMonth = calendar.get(Calendar.MONTH);
        int beginYear = calendar.get(Calendar.YEAR);

        calendar.setTime(nowTime);
        int nowDay = calendar.get(Calendar.DAY_OF_MONTH);
        int nowMonth = calendar.get(Calendar.MONTH);
        int nowYear = calendar.get(Calendar.YEAR);
        Map<String, Object> map = new HashMap<>(5);
        int result;
        if (beginYear == nowYear && nowMonth != beginMonth) {
            result = nowMonth - beginMonth; //返回相差月份
            map.put("month", result);
        } else if (beginYear == nowYear && nowMonth == beginMonth && beginDay != nowYear) {
            result = nowDay - beginDay; //返回相差天数
            map.put("day", result);
        } else {
            result = nowYear - beginYear;
            map.put("year", result); //返回相差年份
        }
        return map;
    }



    /***
     * 日期月份减一个月
     *
     * @param datetime
     *            日期(2014-11)
     * @return 2014-10
     */
    public static String dateFormat(String datetime) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        Date date = null;
        try {
            date = sdf.parse(datetime);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar cl = Calendar.getInstance();
        cl.setTime(date);
        cl.add(Calendar.MONTH, -1);
        date = cl.getTime();
        return sdf.format(date);
    }

    public static String dateFormat(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        return sdf.format(date);
    }

    /****
     * 传入具体日期 ，返回具体日期减一个月。
     *
     * @param date
     *            日期(2014-04-20)
     * @return 2014-03-20
     * @throws ParseException
     */
    public static String subMonth(String date) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date dt = sdf.parse(date);
        Calendar rightNow = Calendar.getInstance();
        rightNow.setTime(dt);

        rightNow.add(Calendar.MONTH, -1);
        Date dt1 = rightNow.getTime();
        String reStr = sdf.format(dt1);

        return reStr;
    }

    /****
     * 获取月末最后一天
     *
     * @param sDate
     *            2014-11-24
     * @return 30
     */
    private static String getMonthMaxDay(String sDate) {
        SimpleDateFormat sdfFull = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();
        Date date = null;
        try {
            date = sdfFull.parse(sDate + "-01");
        } catch (ParseException e) {
            e.printStackTrace();
        }
        cal.setTime(date);
        int last = cal.getActualMaximum(Calendar.DATE);
        return String.valueOf(last);
    }


    /***
     * 日期减月份、加月份
     *
     * @param option
     *            传入类型 pre：日期减一天，next：日期加一天
     * @param nowDate
     *            2014-11-24
     *
     * @param day 需要加减的天
     * @return 减一天：2014-11-23或(加一天：2014-11-25)
     */
    public static String checkOption(String option, String nowDate, Integer day) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        Date date = null;
        try {
            date = sdf.parse(nowDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        calendar.setTime(date);
        if ("pre".equals(option)) {
            // 时间减月
            calendar.add(Calendar.DAY_OF_MONTH, -day);

        } else if ("next".equals(option)) {
            // 时间加月
            calendar.add(Calendar.DAY_OF_MONTH, day);
        } else {
            // do nothing
        }
        date = calendar.getTime();
        return sdf.format(date);
    }

    /***
     * 判断日期是否为当前月， 是当前月返回当月最小日期和当月目前最大日期以及传入日期上月的最大日和最小日
     * 不是当前月返回传入月份的最大日和最小日以及传入日期上月的最大日和最小日
     *
     * @param date
     *            日期 例如：2014-11
     * @return String[] 开始日期，结束日期，上月开始日期，上月结束日期
     * @throws ParseException
     */
    public static String[] getnowPreDate(String date) throws ParseException {

        String[] strDate = new String[4];
        Date now = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        SimpleDateFormat sdfFull = new SimpleDateFormat("yyyy-MM-dd");
        String stMonth = sdf.format(now);
        String stDate = "";// 开始日期
        String endDate = "";// 结束日期
        String predateStart = "";// 上月开始日期
        String predateEnd = "";// 上月结束日期

        // 当前月
        if (date.equals(stMonth)) {
            stDate = stMonth + "-01";
            endDate = sdfFull.format(now);
            predateStart = subMonth(stDate);
            predateEnd = subMonth(endDate);
        } else {
            // 非当前月
            String monthMaxDay = getMonthMaxDay(date);
            stDate = date + "-01";
            endDate = date + "-" + monthMaxDay;
            predateStart = subMonth(stDate);
            predateEnd = subMonth(endDate);
        }
        strDate[0] = stDate;
        strDate[1] = endDate;
        strDate[2] = predateStart;
        strDate[3] = predateEnd;

        return strDate;
    }

    /**
     * 获取随机日期
     *
     * @param beginDate
     *            起始日期，格式为：yyyy-MM-dd
     * @param endDate
     *            结束日期，格式为：yyyy-MM-dd
     * @return
     */

    public static Date randomDate(String beginDate, String endDate) {
        try {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            Date start = format.parse(beginDate);// 构造开始日期
            Date end = format.parse(endDate);// 构造结束日期
            // getTime()表示返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
            if (start.getTime() >= end.getTime()) {
                return null;
            }
            long date = random(start.getTime(), end.getTime());

            return new Date(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private static long random(long begin, long end) {
        long rtn = begin + (long) (Math.random() * (end - begin));
        // 如果返回的是开始时间和结束时间，则递归调用本函数查找随机值
        if (rtn == begin || rtn == end) {
            return random(begin, end);
        }
        return rtn;
    }


    /**
     * 获取日期中的年份
     */
    public static String getYear(Date date){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy");
        return simpleDateFormat.format(date);
    }
    public static String getDay(Date date){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd");
        return simpleDateFormat.format(date);
    }


    public static Date localDate2Date(java.time.LocalDate localDate){
        return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

    public static Date localDate2DateTime(java.time.LocalDateTime localDate){
        return Date.from(localDate.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static java.time.LocalDate date2LocalDate(Date date){
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    public static java.time.LocalDateTime date2LocalDateTime(Date date){
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }
}
